package com.le.tester.javaThink.fourth.concurrency;


import com.le.tester.javaThink.fourth.net.mindview.util.BasicGenerator;
import com.le.tester.javaThink.fourth.net.mindview.util.Generator;
import org.aspectj.weaver.patterns.IfPointcut;

import java.util.List;
import java.util.concurrent.*;

/**
 * createTime：2022/1/17 11:05
 * description：exchangerDemo
 */

class ExchangerProduce<T> implements Runnable {

    private Generator<T> generator;

    private Exchanger<List<T>> exchangers;

    private List<T> holder;

    ExchangerProduce(Exchanger<List<T>> exchangerProduces, Generator<T> gen, List<T> holder) {
        this.exchangers = exchangerProduces;
        this.generator = gen;
        this.holder = holder;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                for (int i = 0; i < ExchangerDemo.size; i++) {
                    holder.add(generator.next());
                }
                holder = exchangers.exchange(holder);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e.getMessage());
        }
    }
}

class ExchangerConsumer<T> implements Runnable {

    private Exchanger<List<T>> exchanger;

    private List<T> holder;

    private volatile T value;

    public ExchangerConsumer(Exchanger<List<T>> exchanger, List<T> holder) {
        this.exchanger = exchanger;
        this.holder = holder;
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                holder = exchanger.exchange(holder);
                for (T x : holder) {
                    value = x;
                    holder.remove(x);
                }
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e.getMessage());
        }
        System.out.println("Final value: " + value);
    }
}

public class ExchangerDemo {
    static int size = 10;
    static int delay = 5;

    public static void main(String[] args) throws InterruptedException {
        if (args.length > 0)
            size = new Integer(args[0]);
        if (args.length > 1)
            delay = new Integer(args[1]);
        ExecutorService exec = Executors.newCachedThreadPool();
        Exchanger<List<Fat>> xc = new Exchanger<>();
        List<Fat> producerList = new CopyOnWriteArrayList<>(),
                consumerList = new CopyOnWriteArrayList<>();

        exec.execute(new ExchangerProduce<>(xc, BasicGenerator.create(Fat.class), producerList));

        exec.execute(new ExchangerConsumer<>(xc, consumerList));

        TimeUnit.SECONDS.sleep(delay);

        exec.shutdownNow();
    }
}
